﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using GraphSharp;
using QuickGraph;
using snat.model;
using snat.algorithms.network;
using System.Threading;

namespace gui
{
    /// <summary>
    /// Interaction logic for GraphicsTab.xaml
    /// </summary>
    public partial class GraphicsTab : UserControl
    {
        private bool debug = false;
        private bool useTestGraph = false;
        private int testGraphSize = 100;

        private bool nodeFiltersChanged = false;
        private bool edgeFiltersChanged = false;

        private List<Edge> viewEdges = new List<Edge>();
        private List<BaseNode> viewNodes = new List<BaseNode>();

        private NetworkViewModel viewModel = new NetworkViewModel(NetworkModel.Instance.Nodes, NetworkModel.Instance.Edges);
        public NetworkViewModel ViewModel {
            get {
                return viewModel;
            }
        }


        public GraphicsTab() { 
            NetworkModel.Instance.NewEdge += viewModel.EdgeListener;
            NetworkModel.Instance.NewNode += viewModel.NodeListener;

            ConnectionViewModel vm = new ConnectionViewModel();
            DataContext = vm;

            NetworkModel.Instance.Init();

            InitializeComponent();
        }
        
        private void ApplyFilters(object sender, RoutedEventArgs e) {
            graphLayout.Relayout(); // Perform layout shuffle
        }

        #region -----FILTERS-----
        private void UpdateEdgeFilterList(object sender, RoutedPropertyChangedEventArgs<double> e) {

            try
            {
                switch (EdgeFilter.SelectedValue.ToString())
                {
                    default: Console.WriteLine("GUI :: Filter not yet implemented"); break;
                }
            }
            catch (NullReferenceException)
            {
                Console.WriteLine("GUI :: Filter not yet implemented");
            }
        }


        private void AddFilter(object sender, RoutedEventArgs e) {

        }

        private void RemoveFilter(object sender, RoutedEventArgs e) {

        }
        #endregion

        private void PlayAlgorithm(object sender, RoutedEventArgs e) {
            if (!useTestGraph) {
                if(debug) Console.WriteLine("GUI :: Playing algorithm - adding all edges");
                Thread player = new Thread(new ThreadStart(NetworkModel.Instance.Play));
                //player.IsBackground = true;
                player.Start();
                //currentMessageCount = MaxMessages();
            }
            else {
                DisplayDialog("You are currently running with a static model and data source. Therefore there is nothing to play.");
            }
        }

        private void PauseAlgorithm(object sender, RoutedEventArgs e) {
            NetworkModel.Instance.Pause();
        }

        private void StepByAlgorithm(object sender, RoutedEventArgs e) {
            if (!useTestGraph) {
                if (debug) Console.WriteLine("GUI :: Jumping By {0} steps.", (int)JumpIndex.Value);
                NetworkModel.Instance.Step((int)JumpIndex.Value);
                //currentMessageCount += (int)JumpIndex.Value
            }
            else {
                DisplayDialog("You are currently running with a static model and data source. Therefore there is nothing to step to.");
            }
        }

        public void DisplayDialog(string message) {
            string sCaption = "SNAT System Message";
            MessageBoxButton btnMessageBox = MessageBoxButton.OK;
            MessageBoxImage icnMessageBox = MessageBoxImage.Warning;
            string sMessageBoxText = "SNAT System Message :: " + message;
            MessageBoxResult rsltMessageBox = MessageBox.Show(sMessageBoxText, sCaption, btnMessageBox, icnMessageBox);
        }

        public void ExceptionBox(string message) {
            string sCaption = "SNAT Exception";
            MessageBoxButton btnMessageBox = MessageBoxButton.OK;
            MessageBoxImage icnMessageBox = MessageBoxImage.Warning;
            string sMessageBoxText = "SNAT Program Exception :: " + message;
            MessageBoxResult rsltMessageBox = MessageBox.Show(sMessageBoxText, sCaption, btnMessageBox, icnMessageBox);
            if (rsltMessageBox == MessageBoxResult.OK) Application.Current.Shutdown();
        }

    }

    // -------------------------------
    // Custom classes
    // -------------------------------

    // Dropdown filters menu
    public class EdgeFilterType {
        public string Type { get; set; }
        public EdgeFilterType(string type) {
            Type = type;
        }
    }

   

    // Build bound View Model components
    public class ConnectionViewModel : INotifyPropertyChanged {
        public ConnectionViewModel() {

            // Build Combo Box
            IList<EdgeFilterType> list = new List<EdgeFilterType>();
            list.Add(new EdgeFilterType("Out Degree"));
            list.Add(new EdgeFilterType("In Degree"));
            list.Add(new EdgeFilterType("Total Degree"));
            list.Add(new EdgeFilterType("Custom Influence Filter"));
            edgeFilterTypeList = new CollectionView(list);
        }


        // Edge Filter Type List Combo Box
        private readonly CollectionView edgeFilterTypeList;
        public string edgeFilter;
        public CollectionView EdgeFilterTypeList {
            get { return edgeFilterTypeList; }
        }
        public string EdgeFilter {
            get { return edgeFilter; }
            set {
                if (edgeFilter == value) return;
                edgeFilter = value;
                OnPropertyChanged("EdgeFilter");
            }
        }


        private void OnPropertyChanged(string propertyName) {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}
